#ifndef OGRE_MANAGER_H
#define OGRE_MANAGER_H
#include "GlobalConfig.h"
#include "OgrePreDeclare.h"
#include <OGRE\Ogre.h>
#include "OgreWindow.h"
#include "system.h"
namespace DAISY{

typedef  boost::shared_ptr<OgreWindow>  OgreWindowPtr;

class OgreManager: public WindowListener
{
public:
	OgreManager():
_root(),
_window(),
_sceneManager(NULL),
_camera(NULL),
_viewport(NULL),
_init(false),
_exit(false){}
	~OgreManager(){}
private:
	void createSceneManager()
	{
		_sceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
	}
	void destroySceneManager()
	{
		Ogre::Root::getSingleton().destroySceneManager(_sceneManager);
		_sceneManager = 0;
	}

	void createCamera()
	{
		_camera = _sceneManager->createCamera("PlayerCam");
		_camera->setNearClipDistance(5);
	}
	void destroyCamera()
	{

	}

	void createViewports(void)
	{
		_viewport = _window->getRenderWindow()->addViewport(_camera);
		_camera->setAspectRatio(Ogre::Real(_viewport->getActualWidth()) / Ogre::Real(_viewport->getActualHeight()));
		_viewport->setBackgroundColour(Ogre::ColourValue::Green);
	}
	void destroyViewports(void){}


	void loadResources(void)
	{
		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	}



	void createSimpleScene(void){}
	void destroySimpleScene(void){}

	OgreWindowPtr createRenderWindowIn()
	{
		return OgreWindowPtr(new OgreWindowIn(this));
	}
	OgreWindowPtr createRenderWindowOut(WeakWindowPtr win)
	{
		return boost::shared_ptr<OgreWindowOut>(new OgreWindowOut(win, this));
	}
	virtual void onSizeChange(size_t width, size_t height)
	{
		assert(_camera);
		getRenderWindow()->windowMovedOrResized();
		_camera->setAspectRatio(Ogre::Real(width) / Ogre::Real(height));
	}
	virtual void onClosed(){_exit = true;}
	void setupResources()
	{
		Ogre::ConfigFile cf;
		cf.load("resources_d.cfg");
		Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
		Ogre::String secName, typeName, archName;
		while (seci.hasMoreElements())
		{
			secName = seci.peekNextKey();
			Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
			Ogre::ConfigFile::SettingsMultiMap::iterator i;
			for (i = settings->begin(); i != settings->end(); ++i)
			{
				typeName = i->first;
				archName = i->second;
				Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
			}
		}
	}
	void clearResources(){}
	boost::scoped_ptr<Ogre::Root> _root;
	OgreWindowPtr _window;
	Ogre::SceneManager * _sceneManager;
	Ogre::Camera * _camera;
	Ogre::Viewport* _viewport;
	bool _init;
	bool _exit;
	
public:
	inline Ogre::Camera * getCamera()
	{
		return _camera;
	}
	inline Ogre::SceneManager * getSceneManager()
	{
		return _sceneManager;
	}
	Ogre::RenderWindow * getRenderWindow()
	{
		return _window->getRenderWindow();//TODO
	}
	bool update(TimeType interval)
	{
		if(_init)
		_window->render();
		return !_exit;
	}
	bool init()
	{
		//Ogre::Root* root = new Ogre::Root("plugins_d.cfg");
		_root.reset(new Ogre::Root("plugins_d.cfg","ogre.cfg","Ogre.log"));
		if(!_root->showConfigDialog())
		{
			//SystemInterface::getSingleton().exit();
			return false;
		}
	
		/*if(_root->restoreConfig())
		{
			 mWindow = mRoot->initialise(true,"DAISY");
        return true;
		}*/
		setupResources();
	
		if(SystemInterface::getInstancePtr()->hasParame("WINDOW"))
		{
			Ogre::Root::getSingleton().initialise(false, "DAISY Window");
			WeakWindowPtr win;
			try
			{
				win = SystemInterface::getInstancePtr()->getParame<WeakWindowPtr>("WINDOW");
			}
			catch(...)
			{
				std::cout<<"bool init(void) error"<<std::endl;
			}

			_window = createRenderWindowOut(win);
			//!!_window->addListener(this);
		}
		else
		{
			Ogre::Root::getSingleton().initialise(true, "DAISY Window");
			_window = createRenderWindowIn();
			//!!_window->addListener(this);
		}
	
		loadResources();
		createSceneManager();
		createCamera();
		createViewports();

		Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	
		createSimpleScene();



		_init = true;
		//createRenderWindow();
		return true;
	}
	void shutdown()
	{
		_init = false;
		destroySimpleScene();
		clearResources();
		destroyViewports();
		destroyCamera();
		destroySceneManager();
		_window.reset();
		_root.reset();
	}
	bool run(){return true;}
	
	

public:
	Ogre::Root *mRoot;
    Ogre::Camera* mCamera;
    Ogre::SceneManager* mSceneMgr;
    Ogre::RenderWindow* mWindow;
    Ogre::String mResourcesCfg;
    Ogre::String mPluginsCfg;

};

SystemUnit_BEGIN(OgreManager)
SystemUnit_INIT
SystemUnit_UPDATE
SystemUnit_SHUTDOWN
SystemUnit_RUN
SystemUnit_END(OgreManager)
}
#endif